{{>licenseInfo}}
import { DiscoveryApi } from '../types/discovery';
import { FetchApi } from '../types/fetch';
import crossFetch from 'cross-fetch';
import {pluginId} from '../pluginId';
import * as parser from 'uri-template';

{{#imports}}
import { {{classname}} } from '{{filename}}.model{{importFileExtension}}';
{{/imports}}

/**
 * Wraps the Response type to convey a type on the json call.
 *
 * @public
 */
export type TypedResponse<T> = Omit<Response, 'json'> & {
  json: () => Promise<T>;
};

{{#operations}}

/**
 * Options you can pass into a request for additional information.
 *
 * @public
 */
export interface RequestOptions {
  token?: string;
}

/**
 * {{{description}}}{{^description}}no description{{/description}}
 */
export class {{classname}}Client {
    private readonly discoveryApi: DiscoveryApi;
    private readonly fetchApi: FetchApi;

    constructor(options: {
        discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };
        fetchApi?: { fetch: typeof fetch };
    }) {
        this.discoveryApi = options.discoveryApi;
        this.fetchApi = options.fetchApi || { fetch: crossFetch };
    }

    {{#operation}}
    /**
     {{#notes}}
     * {{&notes}}
     {{/notes}}
     {{#summary}}
     * {{&summary}}
     {{/summary}}
     {{#allParams}}
     * @param {{paramName}} {{description}}
     {{/allParams}}
     */
    public async {{nickname}}(
        // @ts-ignore
        request: {
            {{#hasPathParams}}
            path: {
                {{#pathParams}}
                    {{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
                {{/pathParams}}
            },
            {{/hasPathParams}}
            {{#hasBodyParam}}
                {{#bodyParam}}
                body: {{{dataType}}},
                {{/bodyParam}}
            {{/hasBodyParam}}
            {{#hasQueryParams}}
            query: {
                {{#queryParams}}
                {{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
                {{/queryParams}}
            },
            {{/hasQueryParams}}
            {{#hasHeaderParams}}
            header: {
                {{#headerParams}}
                {{paramName}}{{^required}}?{{/required}}: {{{dataType}}},
                {{/headerParams}}
            },
            {{/hasHeaderParams}}
        },
        options?: RequestOptions
    ): Promise<TypedResponse<{{{returnType}}} {{^returnType}}void{{/returnType}}>> {
        const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);

        const uriTemplate = `{{{path}}}{{#hasQueryParams}}{?{{#queryParams}}{{baseName}}{{#isArray}}{{#isExplode}}*{{/isExplode}}{{/isArray}}{{^-last}},{{/-last}}{{/queryParams}}}{{/hasQueryParams}}`;

        const uri = parser.parse(uriTemplate).expand({
        {{#pathParams}}
            {{baseName}}: request.path.{{paramName}},
        {{/pathParams}}
        {{#hasQueryParams}}
            ...request.query,
        {{/hasQueryParams}}
        })

        return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
            headers: {
                {{#hasHeaderParams}}
                ...request.header,
                {{/hasHeaderParams}}
                'Content-Type': 'application/json',
                ...(options?.token && { Authorization: `Bearer ${options?.token}` }),
            },
            method: '{{httpMethod}}',
            {{#hasBodyParam}} body: JSON.stringify(request.body), {{/hasBodyParam}}
        });
    }

    {{/operation}}
}
{{/operations}}
